from wormbane.model.thing import Thing
from wormbane.util.format import add_indefinite_article
from wormbane.util.random_ import weighted_choice

import math, random

class Item(Thing):
    is_item = True
    kind = 'item'
    weight = 1
    blessable = True
    beatitude = 'uncursed'
    enchantable = False
    enchantment = 0
    char = '?'
    mergeable = True
    desc_attrs = ('beatitude_prefix', 'kind')
    beatitude_id = False
    enchantment_id = False
    wielded = False

    def __init__(self, **kwargs):
        Thing.__init__(self, **kwargs)
        if self.beatitude == 'random':
            self.beatitude = weighted_choice(blessed = 10, uncursed = 80,
                                            cursed = 10)
        if self.enchantment == 'random':
            self.enchantment = random_enchantment(self.beatitude)

    def split(self, count = 1):
        if count < 1:
            raise ValueError('invalid count for split')
        elif count >= self.count:
            return self
        else:
            self.count -= count
            other = self.clone(count = count)
            if self.env:
                other.move_to(self.env)
            return other

    def can_merge_with(self, other):
        keys = set(self.__dict__.iterkeys())
        keys.update(other.__dict__.iterkeys())
        keys.discard('count')
        keys.discard('mentioned')
        return all(getattr(self, key) == getattr(other, key)
                   for key in keys)

    def merge_with(self, other):
        self.count += other.count
        other.count = 0

    def merge(self):
        if self.mergeable:
            for other in self.env.inv:
                if (self != other and type(self) == type(other)
                    and self.can_merge_with(other)):
                    self.merge_with(other)
                    other.move_to(None)
                    return

    def clone(self, **kwargs):
        """Clone this item.

        The returned clone will have None as environment."""

        dct = dict(self.__dict__)
        dct.pop('env', None)
        dct.pop('inv', None)
        dct.update(kwargs)
        return type(self)(**dct)
    
    @property
    def beatitude_prefix(self):
        if self.beatitude_id:
            yield self.beatitude

    @property
    def enchantment_prefix(self):
        if self.enchantment_id:
            yield '%+d' % self.enchantment

    @property
    def blessed(self):
        return self.beatitude == 'blessed'

    @property
    def uncursed(self):
        return self.beatitude == 'uncursed'

    @property
    def cursed(self):
        return self.beatitude == 'cursed'

    @property
    def wielder(self):
        return self.env if self.wielded else None

def random_beatitude():
    return weighted_choice(cursed = 10, uncursed = 80, blessed = 10)

def random_enchantment(beatitude = None):
    def magnitude():
        result = 0
        while not random.randrange(5):
            result += 1
        return result
    return (random.choice((-1, +1)) * magnitude()
            + dict(cursed = -1, blessed = +1).get(beatitude, 0))
